package cn.wizzer.app.sys.modules.services.impl;

import cn.wizzer.app.sys.modules.models.Sys_dict;
import cn.wizzer.app.sys.modules.services.SysDictService;
import cn.wizzer.framework.base.Result;
import cn.wizzer.framework.base.service.BaseServiceImpl;
import org.nutz.aop.interceptor.ioc.TransAop;
import org.nutz.dao.Chain;
import org.nutz.dao.Cnd;
import org.nutz.dao.Dao;
import org.nutz.dao.Sqls;
import org.nutz.ioc.aop.Aop;
import org.nutz.ioc.loader.annotation.IocBean;
import org.nutz.lang.Strings;
import org.nutz.lang.util.NutMap;
import org.nutz.mvc.annotation.Param;
import org.nutz.plugins.wkcache.annotation.CacheDefaults;
import org.nutz.plugins.wkcache.annotation.CacheRemoveAll;
import org.nutz.plugins.wkcache.annotation.CacheResult;

import java.util.*;


@IocBean(args = {"refer:dao"})
@CacheDefaults(cacheName = "sys_dict")
public class SysDictServiceImpl extends BaseServiceImpl<Sys_dict> implements SysDictService {
    public SysDictServiceImpl(Dao dao) {
        super(dao);
    }

    /**
     * 通过code获取name
     *
     * @param code
     * @return
     */
    @CacheResult
    public String getNameByCode(String code,String parentCode) {
        Sys_dict dict = this.fetch(Cnd.where("code", "=", code).and("parentId","=",this.fetch(Cnd.where("code", "=", parentCode)).getId()));
        return dict == null ? "" : dict.getName();
    }

    @CacheResult
    public String getProcessCode(String name) {
        Sys_dict dict = this.fetch(Cnd.where("name", "=", name));
        return dict == null ? "" : dict.getCode();
    }

    /**
     * 通过id获取name
     *
     * @param id
     * @return
     */
    @CacheResult
    public String getNameById(String id) {
        Sys_dict dict = this.fetch(id);
        return dict == null ? "" : dict.getName();
    }

    /**
     * 通过树path获取下级列表
     *
     * @param path
     * @return
     */
    @CacheResult
    public List<Sys_dict> getSubListByPath(String path) {
        return this.query(Cnd.where("path", "like", Strings.sNull(path) + "____").asc("location"));
    }

    /**
     * 通过父id获取下级列表
     *
     * @param id
     * @return
     */
    @CacheResult
    public List<Sys_dict> getSubListById(String id) {
        return this.query(Cnd.where("parentId", "=", Strings.sNull(id)).asc("location"));
    }

    /**
     * 通过code获取下级列表
     *
     * @param code
     * @return
     */
    @CacheResult
    public List<Sys_dict> getSubListByCode(String code) {
        Sys_dict dict = this.fetch(Cnd.where("code", "=", code));
        return dict == null ? new ArrayList<>() : this.query(Cnd.where("parentId", "=", Strings.sNull(dict.getId())).asc("location"));
    }

    /**
     * 通过path获取下级map
     *
     * @param path
     * @return
     */
    @CacheResult
    public Map getSubMapByPath(String path) {
        return this.getMap(Sqls.create("select code,name from sys_dict where path like @path order by location asc").setParam("path", path + "____"));
    }

    /**
     * 通过id获取下级map
     *
     * @param id
     * @return
     */
    @CacheResult
    public Map getSubMapById(String id) {
        return this.getMap(Sqls.create("select code,name from sys_dict where parentId = @id order by location asc").setParam("id", id));
    }

    /**
     * 通过code获取下级map
     *
     * @param code
     * @return
     */
    @CacheResult
    public Map getSubMapByCode(String code) {
        Sys_dict dict = this.fetch(Cnd.where("code", "=", code));
        return dict == null ? new HashMap() : this.getMap(Sqls.create("select code,name from sys_dict where parentId = @id order by location asc").setParam("id", dict.getId()));
    }

    /**
     * 新增字典
     *
     * @param dict
     * @param pid
     */
    @Aop(TransAop.READ_COMMITTED)
    public void save(Sys_dict dict, String pid) {
        String path = "";
        if (!Strings.isEmpty(pid)) {
            Sys_dict pp = this.fetch(pid);
            path = pp.getPath();
        }
        dict.setPath(getSubPath("sys_dict", "path", path));
        dict.setParentId(pid);
        dao().insert(dict);
        if (!Strings.isEmpty(pid)) {
            this.update(Chain.make("hasChildren", true), Cnd.where("id", "=", pid));
        }
    }

    /**
     * 级联删除单位
     *
     * @param dict
     */
    @Aop(TransAop.READ_COMMITTED)
    public void deleteAndChild(Sys_dict dict) {
        dao().execute(Sqls.create("delete from sys_dict where path like @path").setParam("path", dict.getPath() + "%"));
        if (!Strings.isEmpty(dict.getParentId())) {
            int count = count(Cnd.where("parentId", "=", dict.getParentId()));
            if (count < 1) {
                dao().execute(Sqls.create("update sys_dict set hasChildren=0 where id=@pid").setParam("pid", dict.getParentId()));
            }
        }
    }

    @CacheRemoveAll
    public void clearCache() {

    }

    public List<NutMap> dictTreeChild(String code){
        List<NutMap> treeList = new ArrayList<>();
        Cnd cnd = Cnd.NEW();
        if (!Strings.isBlank(code)) {
            cnd.and("code", "=", code);
            Sys_dict dict = this.fetch(cnd);
            treeList=getDictTreeChild(dict.getId());
        }
        return treeList;
    }
    public List<NutMap> dictTreeChilds(String[] ids,List<NutMap> list){
        for (String dict_id : ids){
            for (NutMap map : list){
                if(dict_id.equals(map.get("value"))){
                    String id = dict_id;
                    Sys_dict dict = this.fetch(id);
                    if (dict.isHasChildren()) {
                        Cnd cnd = Cnd.NEW();
                        cnd.and("parentId", "=", dict_id);
                        cnd.asc("location").asc("path");
                        List<Sys_dict> listChildren = this.query(cnd);
                        List<NutMap> treeList = new ArrayList<>();
                        for (Sys_dict sysDict : listChildren) {
                            NutMap mapChildren = NutMap.NEW().addv("value", sysDict.getId()).addv("label", sysDict.getName()).addv("code",sysDict.getCode()).addv("leaf",!sysDict.isHasChildren());
                            treeList.add(mapChildren);
                        }
                        String[] newIdsx = Arrays.copyOfRange(ids, 1, ids.length);
                        map.addv("children", dictTreeChilds(newIdsx,treeList));
                    }
                }
            }
        }
        return list;
    }

    public List<NutMap> getDictTreeChild(String parentId){
        List<NutMap> treeList = new ArrayList<>();
        Cnd cnd = Cnd.NEW();
        cnd.and("parentId", "=", parentId);
        cnd.asc("location").asc("path");
        List<Sys_dict> list = this.query(cnd);
        for (Sys_dict sysDict : list) {
            NutMap map = NutMap.NEW().addv("value", sysDict.getId()).addv("label", sysDict.getName()).addv("code",sysDict.getCode()).addv("leaf",!sysDict.isHasChildren());
            /*if (sysDict.isHasChildren()) {
                map.addv("children", getDictTree(sysDict.getId()));
            }*/
            treeList.add(map);
        }
        return treeList;
    }

    public List<NutMap> dictTree(String code){
            List<NutMap> treeList = new ArrayList<>();
            Cnd cnd = Cnd.NEW();
            if (!Strings.isBlank(code)) {
                cnd.and("code", "=", code);
                Sys_dict dict = this.fetch(cnd);
                treeList=getDictTree(dict.getId());
            }
            return treeList;
    }

    public List<NutMap> getDictTree(String parentId){
        List<NutMap> treeList = new ArrayList<>();
        Cnd cnd = Cnd.NEW();
        cnd.and("parentId", "=", parentId);
        cnd.asc("location").asc("path");
        List<Sys_dict> list = this.query(cnd);
        for (Sys_dict sysDict : list) {
            NutMap map = NutMap.NEW().addv("value", sysDict.getId()).addv("label", sysDict.getName()).addv("code",sysDict.getCode());
            if (sysDict.isHasChildren()) {
                map.addv("children", getDictTree(sysDict.getId()));
            }
            treeList.add(map);
        }
        return treeList;
    }

    public List<NutMap> dictCodeTree(String code){
        List<NutMap> treeList = new ArrayList<>();
        Cnd cnd = Cnd.NEW();
        if (!Strings.isBlank(code)) {
            cnd.and("code", "=", code);
            Sys_dict dict = this.fetch(cnd);
            treeList=getDictCodeTree(dict.getId());
        }
        return treeList;
    }

    public List<NutMap> getDictCodeTree(String parentId){
        List<NutMap> treeList = new ArrayList<>();
        Cnd cnd = Cnd.NEW();
        cnd.and("parentId", "=", parentId);
        cnd.asc("location").asc("path");
        List<Sys_dict> list = this.query(cnd);
        for (Sys_dict sysDict : list) {
            NutMap map = NutMap.NEW().addv("value", sysDict.getCode()).addv("label", sysDict.getName());
            if (sysDict.isHasChildren()) {
                map.addv("children", getDictCodeTree(sysDict.getId()));
            }
            treeList.add(map);
        }
        return treeList;
    }
    public Map getCodeMap(String code){
        String sql =" SELECT sd.code, sd. NAME FROM sys_dict sd WHERE path like CONCAT((select path from sys_dict where code='"+code+"'),'%') ";
        Map map = this.getMap(Sqls.create(sql));
        return map;
    }

    public Map getIdMap(String code){
        String sql =" SELECT sd.id, sd. NAME FROM sys_dict sd WHERE path like CONCAT((select path from sys_dict where code='"+code+"'),'%') ";
        Map map = this.getMap(Sqls.create(sql));
        return map;
    }
}
